﻿// ========================================================================
// Projectile.cs
// by T. Jared Smith
// ========================================================================

// #define DEBUG_CIRCLE

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using MathUtil;
using Physics;
using Geometry;

namespace Tank
{
    public enum Projectile_Type
    {
        SHELL,
        PLASMA,
        ELECTRO
    }

    public class Projectile : CircularSprite
    {
        private uint damage;
        private float maxFlightTime;                // maximum time in flight
        private float timeInFlight;                 // total time in flight
        private float angle;                        // top down direction in radians
        private Vector2 direction;                  // same as direction, in vector format
        private bool hitTarget;
        private bool isLive;                        // round is still moving
        private bool remove;
        Frame currFrame;                            // frame to draw 
        ParticleEmitter explosion;
        Projectile_Type pType;

        public Projectile(Vector2 _pos, float _maxVel, float _maxAccel,
            float _drag, string _textureID, string _name, float _radius,
            uint _damage, float _maxTime, Vector2 _direction, float _angle)
            : base(_pos, _maxVel, _maxAccel, _drag, _textureID, _name, _radius)
        {
            pType = Projectile_Type.SHELL;
            damage = _damage;
            maxFlightTime = _maxTime;
            direction = _direction;
            hitTarget = false;
            isLive = true;
            remove = false;
            angle = _angle;
          
            currFrame = new Frame();
            currFrame.x = 178;
            currFrame.y = 136;
            currFrame.width = 4;
            currFrame.height = 40;
        }

        public override void Update(float deltaTime)
        {
            // is round live?
            if (remove)
            {
                return;
            }

            timeInFlight += deltaTime;
            if (timeInFlight >= maxFlightTime)
            {
                isLive = false;
                remove = true;
                return;
            }

            if (isLive)
            {
                base.Update(deltaTime);
            }
            // Update Explosion Particle Emitter if not alive
            else
            {
                explosion.Update(deltaTime);
            }
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            if (remove)
                return;

            if (isLive)
            {
                Texture2D texture = World.Instance.GetTexture(TextureID);
                Rectangle drawRect = new Rectangle(currFrame.x, currFrame.y, currFrame.width, currFrame.height);
                Vector2 drawPos = new Vector2(Position.X, Position.Y);
                spriteBatch.Draw(texture, Position, drawRect, Color.White, angle, new Vector2(), 1.0f, SpriteEffects.None, 0.0f);

#if DEBUG_CIRCLE
                Texture2D debugTexture = World.Instance.GetTexture("DebugCircle");
                spriteBatch.Draw(debugTexture,
                                 new Vector2(BoundSphere.Center.X - debugTexture.Width * 0.5f,
                                             BoundSphere.Center.Y - debugTexture.Height * 0.5f),
                                  Color.White);
#endif // DEBUG_CIRCLE
            }
            // Otherwise, we are exploding
            else
            {
                explosion.Draw(spriteBatch);
            }
        }               

        // Explode this projectile
        public void Explode(bool targetIsHit, Projectile_Type type)
        {
            if (!isLive)
                return;
            isLive = false;
            if (targetIsHit)
                hitTarget = true;

            explosion = new ParticleEmitter(40, Position, new Vector2(), -direction, 300, 0.17f, 6.0f,
                                            0, 5, Color.WhiteSmoke, 1, 0, 0.8f, 0, 20);

            if (type == Projectile_Type.PLASMA)
                explosion.SetTexture("PlasmaBlast", new Rectangle(10, 10, 125, 125));
            else
                explosion.SetTexture("dust", new Rectangle(0, 0, 31, 31));

            //explosion.SetFadeSize(0.1f, 1.0f);
            //explosion.SetFadeStyle(ParticleFadeStyle.EXPAND);
            explosion.EmitOnce();

			// Sound: Tank Damage Explosion. TODO: Add non tank damage explosion...
			int num = SoundManager.Instance.Random.Next(0, 2);
			SoundType s = num < 1 ? SoundType.TANK_DAMAGE_1 : SoundType.TANK_DAMAGE_2;
			SoundManager.Instance.PlaySound(s, true); 
		}

        public uint Damage
        {
            get { return damage; }
        }

        public bool HitTarget
        {
            get { return hitTarget; }
        }

        public bool IsLive
        {
            get { return isLive; }
            set { isLive = value; }
        }

        public bool Remove
        {
            get { return remove;  }
        }

        public Projectile_Type PType
        {
            get { return pType; }
            set { pType = value; }
        }

        public Frame CurrFrame
        {
            get { return currFrame; }
            set { currFrame = value; }
        }

 
        
    }

    #region Plasma
    class Plasma :Projectile
    {
        
        public Plasma(Vector2 _pos, float _maxVel, float _maxAccel,
            float _drag, string _textureID, string _name, float _radius,
            uint _damage, float _maxTime, Vector2 _direction, float _angle)
            :base(_pos, _maxVel, _maxAccel, _drag, _textureID, _name, _radius, _damage, _maxTime, _direction, _angle)
        {
            PType = Projectile_Type.PLASMA;
            CurrFrame.x = 15;
            CurrFrame.y = 15;
            CurrFrame.width = 70;
            CurrFrame.height = 70;
        }


    }
    #endregion

    #region Electro
    class Electro : Projectile
    {
        public Electro(Vector2 _pos, float _maxVel, float _maxAccel,
            float _drag, string _textureID, string _name, float _radius,
            uint _damage, float _maxTime, Vector2 _direction, float _angle)
            :base(_pos, _maxVel, _maxAccel, _drag, _textureID, _name, _radius, _damage, _maxTime, _direction, _angle)
        {
            PType = Projectile_Type.ELECTRO;
        }

    }
    #endregion
}



